#include <gtkmm/drawingarea.h>
#include <list>
#include <glibmm/main.h>
#include <random>
#include <gtkmm/eventcontrollerkey.h>

class gameArea:public Gtk::DrawingArea
{
    public:
        gameArea();
        virtual ~gameArea();

        void gameAreaInit();

        enum keyDirection{Left,Right,Enter,Up,Down,None};
        static keyDirection mKeyDir;

        //signal type
        using signalFinish=sigc::signal<void(void)>;
        using signalSourceChange=sigc::signal<void(unsigned int source)>;
        using signalLiveChange=sigc::signal<void(unsigned int live)>;
        //signal connect function
        signalFinish signal_game_finish()
        {return m_signalFinish;}
        signalSourceChange signal_source_change()
        {return m_signalSourceChange;}
        signalLiveChange signal_live_change()
        {return m_signalLiveChange;}

    protected:
        //signal
        signalFinish m_signalFinish;
        signalSourceChange m_signalSourceChange;
        signalLiveChange m_signalLiveChange;

        void on_drawMain(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height);
        void on_draw(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height);    //draw frame
        void on_drawFrame(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height);
        bool on_timeout();    //game main loop
        
        enum blockType{stone,iron};
        enum gameStatus{start,run,stop,end} m_gameStatus;

    private:
        std::default_random_engine dre;
        std::uniform_int_distribution<int> diH;
        std::uniform_int_distribution<int> diV;
        std::uniform_int_distribution<int> diType;

        int m_live;
        unsigned int m_source;
        const unsigned int m_Vspace;
        static double PFSpeed;

        Glib::RefPtr<Gdk::Pixbuf> imgBackGround;
        Glib::RefPtr<Gdk::Pixbuf> imgPFiro;

        sigc::connection flushTimeout;
        
        class platform;

        class boll
        {
            public:
                boll();
                virtual ~boll();
                enum collisionDirection{Top,Left,Right,None} cDir;
                void draw_W(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height);
                void move();
                bool is_collision(platform & pf);
                unsigned long g_time;
                double Xaxis,Yaxis;
                double i_radius;
                double moveSpeed;
                double resultMoveY;
        };
        boll* mBoll;

        class platform
        {
            public:
                platform(blockType type,double X,double Y,gameArea* parentThis);
                virtual ~platform();
                void draw_W(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height);
                void move();
                inline double getYaxis()
                {return Yaxis;}
                inline double getXaxis()
                {return Xaxis;}
                bool isCollisioned;
                blockType m_type;
            private:
                gameArea* parentPtr;
                friend bool boll::is_collision(platform & pf);
                double Xaxis,Yaxis;
                double i_widget,i_height;
        };

        //loop list
        std::list<std::unique_ptr<platform>> loopListP;
};